package rank

import (
	"sync"

	"github.com/gomodule/redigo/redis"
)

type Manager struct {
	adapt
	instanceMap sync.Map
}

type Position struct {
	Rank  int
	Key   string
	Value int
}

type adapt interface {
	Update(prefix string, key string, value int) error
	Score(prefix string, key string) int
	Count(prefix string) int
	Rank(prefix string, key string, asc bool) int
	Top(prefix string, number int, asc bool) []Position
	Range(prefix string, start int, end int, number int, asc bool) []Position
}

func Default() *Manager {
	m := &Manager{
		instanceMap: sync.Map{},
	}
	return m
}

func (manager *Manager) RegisterRedis(redis *redis.Pool) {
	manager.adapt = NewRedis(redis)
}

func (manager *Manager) getPrefix(region string, identity string) string {
	return "rank://" + region + "/" + identity
}

func (manager *Manager) GetInstance(region string, identity string, asc bool) *rankInstance {
	prefix := manager.getPrefix(region, identity)
	value, ok := manager.instanceMap.Load(prefix)
	if ok {
		v := value.(*rankInstance)
		v.asc = asc
		return v
	}
	instance := &rankInstance{
		prefix: prefix,
		asc:    asc,
		adapt:  manager,
	}
	manager.instanceMap.Store(prefix, instance)
	return instance
}
